home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 4 / QRZ Ham Radio Callsign Database - Volume 4.iso / files / tcpip / amiga / asrc29p.lha / socket.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-29  |  41.9 KB  |  1,889 lines

  1. #include <stdio.h>
  2. #ifdef    __STDC__
  3. #include <stdarg.h>
  4. #endif
  5. #include "global.h"
  6. #include "mbuf.h"
  7. #include "netuser.h"
  8. #include "timer.h"
  9. #include "iface.h"
  10. #include "ip.h"
  11. #include "tcp.h"
  12. #include "udp.h"
  13. #include "ax25.h"
  14. #include "lapb.h"
  15. #include "netrom.h"
  16. #include "nr4.h"
  17. #include "proc.h"
  18. #include "usock.h"
  19. #include "socket.h"
  20. #include "config.h"
  21.  
  22. static void autobind __ARGS((int s,int af));
  23. static int checkaddr __ARGS((int type,char *name,int namelen));
  24. static void rip_recv __ARGS((struct raw_ip *rp));
  25. static void s_trcall __ARGS((struct tcb *tcb,int cnt));
  26. static void s_tscall __ARGS((struct tcb *tcb,int old,int new));
  27. static void s_ttcall __ARGS((struct tcb *tcb,int cnt));
  28. static void s_urcall __ARGS((struct iface *iface,struct udp_cb *udp,int cnt));
  29. static void trdiscard __ARGS((struct tcb *tcb,int cnt));
  30. #ifdef    NETROM
  31. static void s_nrcall __ARGS((struct nr4cb *cb,int cnt));
  32. static void s_nscall __ARGS((struct nr4cb *cb,int old,int new));
  33. static void s_ntcall __ARGS((struct nr4cb *cb,int cnt));
  34. #endif
  35.  
  36. static int16 Lport = 1024;
  37.  
  38. char *Socktypes[] = {
  39.     "Not Used",
  40.     "TCP",
  41.     "UDP",
  42.     "AX25 I",
  43.     "AX25 UI",
  44.     "Raw IP",
  45.     "NETROM3",
  46.     "NETROM",
  47.     "Loc St",
  48.     "Loc Dg"
  49. };
  50. char Badsocket[] = "Bad socket";
  51. struct usock *Usock;        /* Socket entry array */
  52. int Nusock = DEFNSOCK;        /* Number of socket entries */
  53.  
  54. /* The following two variables are needed because there can be only one
  55.  * socket listening on each of the AX.25 modes (I and UI)
  56.  */
  57. #ifdef    AX25
  58. int Axi_sock = -1;    /* Socket number listening for AX25 connections */
  59. static int Axui_sock = -1;    /* Socket number listening for AX25 UI frames */
  60. static struct mbuf *Bcq;    /* Queue of incoming UI frames */
  61.  
  62. /* Function that handles incoming UI frames from lapb.c */
  63. void
  64. beac_input(iface,src,bp)
  65. struct iface *iface;
  66. char *src;
  67. struct mbuf *bp;
  68. {
  69.     struct mbuf *hdr;
  70.     struct sockaddr_ax *sax;
  71.  
  72.     if(Axui_sock == -1){
  73.         /* Nobody there to read it */
  74.         free_p(bp);
  75.     } else {
  76.         if((hdr = pushdown(NULLBUF,sizeof(struct sockaddr_ax))) == NULLBUF){
  77.             free_p(bp);
  78.             return;
  79.         }
  80.         sax = (struct sockaddr_ax *)hdr->data;
  81.         sax->sax_family = AF_AX25;
  82.         memcpy(sax->ax25_addr,src,AXALEN);
  83.         strncpy(sax->iface,iface->name,ILEN);
  84.         hdr->next = bp;
  85.         enqueue(&Bcq,hdr);
  86.     }
  87. }
  88. #endif
  89.  
  90. /* Initialize user socket array */
  91. void
  92. sockinit()
  93. {
  94.     if(Usock != NULLUSOCK)
  95.         return;    /* Already initialized */
  96.     Usock = (struct usock *)callocw(Nusock,sizeof(struct usock));
  97. }
  98.  
  99. /* Create a user socket, return socket index
  100.  * The mapping to actual protocols is as follows:
  101.  *        
  102.  *        
  103.  * ADDRESS FAMILY    Stream        Datagram    Raw        Seq. Packet
  104.  *
  105.  * AF_INET        TCP        UDP        IP
  106.  * AF_AX25        I-frames    UI-frames
  107.  * AF_NETROM                        NET/ROM L3  NET/ROM L4
  108.  * AF_LOCAL        stream loopback    packet loopback
  109.  */
  110. int
  111. socket(af,type,protocol)
  112. int af;        /* Address family */
  113. int type;    /* Stream or datagram */
  114. int protocol;    /* Used for raw IP sockets */
  115. {
  116.     register struct usock *up;
  117.     int s;
  118.  
  119.     for(up=Usock;up < &Usock[Nusock];up++)
  120.         if(up->type == NOTUSED)
  121.             break;
  122.  
  123.     if(up == &Usock[Nusock]){
  124.         /* None left */
  125.         errno = EMFILE;
  126.         return -1;
  127.     }
  128.     up->refcnt = 1;
  129.     s = up - Usock;
  130.     errno = 0;
  131.     up->noblock = 0;
  132.     up->rdysock = -1;
  133.     up->cb.p = NULLCHAR;
  134.     up->peername = up->name = NULLCHAR;
  135.     up->namelen = up->peernamelen = 0;
  136.     up->owner = Curproc;
  137.     up->obuf = NULLBUF;
  138.     memset(up->errcodes,0,sizeof(up->errcodes));
  139.     memset(up->eol,0,sizeof(up->eol));
  140.     up->flush = '\n';    /* default is line buffered */
  141.     switch(af){
  142.     case AF_LOCAL:
  143.         up->cb.local = callocw(1,sizeof(struct loc));
  144.         switch(type){
  145.         case SOCK_STREAM:
  146.             up->type = TYPE_LOCAL_STREAM;
  147.             up->cb.local->hiwat = LOCSFLOW;
  148.             break;
  149.         case SOCK_DGRAM:
  150.             up->type = TYPE_LOCAL_DGRAM;
  151.             up->cb.local->hiwat = LOCDFLOW;
  152.             break;
  153.         default:
  154.             free(up->cb.local);
  155.             errno = ESOCKTNOSUPPORT;
  156.             break;
  157.         }
  158.         break;
  159. #ifdef    AX25
  160.     case AF_AX25:
  161.         switch(type){
  162.         case SOCK_STREAM:
  163.             up->type = TYPE_AX25I;
  164.             break;
  165.         case SOCK_DGRAM:
  166.             up->type = TYPE_AX25UI;
  167.             break;
  168.         default:
  169.             errno = ESOCKTNOSUPPORT;
  170.             break;
  171.         }
  172.         strcpy(up->eol,AX_EOL);
  173.         break;
  174. #endif
  175. #ifdef NETROM
  176.     case AF_NETROM:
  177.         switch(type){
  178.         case SOCK_RAW:
  179.             up->type = TYPE_NETROML3;
  180.             up->cb.rnr = raw_nr((char)protocol);
  181.             break;
  182.         case SOCK_SEQPACKET:
  183.             up->type = TYPE_NETROML4;
  184.             break;
  185.         default:
  186.             errno = ESOCKTNOSUPPORT;
  187.             break;
  188.         }
  189.         strcpy(up->eol,AX_EOL);
  190.         break;
  191. #endif
  192.     case AF_INET:
  193.         switch(type){
  194.         case SOCK_STREAM:
  195.             up->type = TYPE_TCP;
  196.             strcpy(up->eol,INET_EOL);
  197.             break;
  198.         case SOCK_DGRAM:
  199.             up->type = TYPE_UDP;
  200.             break;
  201.         case SOCK_RAW:
  202.             up->type = TYPE_RAW;
  203.             up->cb.rip = raw_ip(protocol,rip_recv);
  204.                         up->cb.rip->user = s;
  205.             break;
  206.         default:
  207.             errno = ESOCKTNOSUPPORT;
  208.             break;
  209.         }
  210.         break;
  211.     default:
  212.         errno = EAFNOSUPPORT;
  213.         break;
  214.     }
  215.     if(errno)
  216.         return -1;
  217.  
  218.     return s;
  219. }
  220.  
  221. /* Attach a local address/port to a socket. If not issued before a connect
  222.  * or listen, will be issued automatically
  223.  */
  224. int
  225. bind(s,name,namelen)
  226. int s;        /* Socket index */
  227. char *name;    /* Local name */
  228. int namelen;    /* Length of name */
  229. {
  230.     register struct usock *up;
  231.     union sp local;
  232.     struct socket lsock;
  233.  
  234.     if((up = itop(s)) == NULLUSOCK){
  235.         errno = EBADF;
  236.         return -1;
  237.     }
  238.     if(up->type == TYPE_LOCAL_STREAM || up->type == TYPE_LOCAL_DGRAM){
  239.         errno = EINVAL;
  240.         return -1;
  241.     }
  242.     if(name == NULLCHAR){
  243.         errno = EFAULT;
  244.         return -1;
  245.     }
  246.     if(up->name != NULLCHAR){
  247.         /* Bind has already been issued */
  248.         errno = EINVAL;
  249.         return -1;
  250.     }
  251.     if(checkaddr(up->type,name,namelen) == -1){
  252.         /* Incorrect length or family for chosen protocol */
  253.         errno = EAFNOSUPP;
  254.         return -1;    
  255.     }
  256.     /* Stash name in an allocated block */
  257.     up->namelen = namelen;
  258.     up->name = mallocw(namelen);
  259.     memcpy(up->name,name,namelen);
  260.     /* Create control block for datagram sockets */
  261.     switch(up->type){
  262.     case TYPE_UDP:
  263.         local.in = (struct sockaddr_in *)up->name;
  264.         lsock.address = local.in->sin_addr.s_addr;
  265.         lsock.port = local.in->sin_port;
  266.         up->cb.udp = open_udp(&lsock,s_urcall);
  267.         up->cb.udp->user = s;
  268.         break;
  269. #ifdef    AX25
  270.     case TYPE_AX25UI:
  271.         if(Axui_sock != -1){
  272.             errno = EADDRINUSE;
  273.             return -1;
  274.         }
  275.         Axui_sock = s;
  276.         break;
  277. #endif
  278.     }
  279.     return 0;
  280. }
  281. /* Post a listen on a socket */
  282. int
  283. listen(s,backlog)
  284. int s;        /* Socket index */
  285. int backlog;    /* 0 for a single connection, 1 for multiple connections */
  286. {
  287.     register struct usock *up;
  288.     union sp local;
  289.     struct socket lsock;
  290.  
  291.     if((up = itop(s)) == NULLUSOCK){
  292.         errno = EBADF;
  293.         return -1;
  294.     }
  295.     if(up->type == TYPE_LOCAL_STREAM || up->type == TYPE_LOCAL_DGRAM){
  296.         errno = EINVAL;
  297.         return -1;
  298.     }
  299.     if(up->cb.p != NULLCHAR){
  300.         errno = EISCONN;
  301.         return -1;
  302.     }
  303.     switch(up->type){
  304.     case TYPE_TCP:
  305.         if(up->name == NULLCHAR)
  306.             autobind(s,AF_INET);
  307.  
  308.         local.in = (struct sockaddr_in *)up->name;
  309.         lsock.address = local.in->sin_addr.s_addr;
  310.         lsock.port = local.in->sin_port;
  311.         up->cb.tcb = open_tcp(&lsock,NULLSOCK,
  312.          backlog ? TCP_SERVER:TCP_PASSIVE,0,
  313.         s_trcall,s_ttcall,s_tscall,0,s);
  314.         break;
  315. #ifdef AX25
  316.     case TYPE_AX25I:
  317.         if(up->name == NULLCHAR)
  318.             autobind(s,AF_AX25);
  319.         if(s != Axi_sock){
  320.             errno = EOPNOTSUPP;
  321.             return -1;
  322.         }
  323.         local.ax = (struct sockaddr_ax *)up->name;
  324.         up->cb.ax25 = open_ax25(NULLIF,local.ax->ax25_addr,NULLCHAR,
  325.          backlog ? AX_SERVER:AX_PASSIVE,0,
  326.          s_arcall,s_atcall,s_ascall,s);
  327.         break;
  328. #endif
  329. #ifdef NETROM
  330.     case TYPE_NETROML4:
  331.         if(up->name == NULLCHAR)
  332.             autobind(s,AF_NETROM);
  333.         local.nr = (struct sockaddr_nr *)up->name;
  334.         up->cb.nr4 = open_nr4(&local.nr->nr_addr,NULLNRADDR,
  335.          backlog ? AX_SERVER:AX_PASSIVE,
  336.          s_nrcall,s_ntcall,s_nscall,s);
  337.         break;
  338. #endif
  339.     default:
  340.         /* Listen not supported on datagram sockets */
  341.         errno = EOPNOTSUPP;
  342.         return -1;        
  343.     }
  344.     return 0;
  345. }
  346. /* Initiate active open. For datagram sockets, merely bind the remote address. */
  347. int
  348. connect(s,peername,peernamelen)
  349. int s;            /* Socket index */
  350. char *peername;        /* Peer name */
  351. int peernamelen;    /* Length of peer name */
  352. {
  353.     register struct usock *up;
  354.     union cb cb;
  355.     union sp local,remote;
  356.     struct socket lsock,fsock;
  357. #ifdef    AX25
  358.     struct iface *iface;
  359. #endif
  360.  
  361.     if((up = itop(s)) == NULLUSOCK){
  362.         errno = EBADF;
  363.         return -1;
  364.     }
  365.     if(up->type == TYPE_LOCAL_DGRAM || up->type == TYPE_LOCAL_STREAM){
  366.         errno = EINVAL;
  367.         return -1;
  368.     }
  369.     if(peername == NULLCHAR){
  370.         /* Connect must specify a remote address */
  371.         errno = EFAULT;
  372.         return -1;
  373.     }
  374.     if(checkaddr(up->type,peername,peernamelen) == -1){
  375.         errno = EAFNOSUPPORT;
  376.         return -1;
  377.     }
  378.     /* Raw socket control blocks are created in socket() */
  379.     if(up->type != TYPE_RAW && up->type != TYPE_NETROML3 &&
  380.        up->cb.p != NULLCHAR){
  381.         errno = EISCONN;
  382.         return -1;
  383.     }
  384.     up->peername = mallocw(peernamelen);
  385.     memcpy(up->peername,peername,peernamelen);
  386.     up->peernamelen = peernamelen;
  387.  
  388.     /* Set up the local socket structures */
  389.     if(up->name == NULLCHAR){
  390.         switch(up->type){
  391.         case TYPE_TCP:
  392.         case TYPE_UDP:
  393.         case TYPE_RAW:
  394.             autobind(s,AF_INET);
  395.             break;
  396. #ifdef    AX25
  397.         case TYPE_AX25I:
  398.         case TYPE_AX25UI:
  399.             autobind(s,AF_AX25);
  400.             break;
  401. #endif
  402. #ifdef    NETROM
  403.         case TYPE_NETROML3:
  404.         case TYPE_NETROML4:
  405.             autobind(s,AF_NETROM);
  406.             break;
  407. #endif
  408.         }
  409.     }
  410.     switch(up->type){
  411.     case TYPE_TCP:
  412.         /* Construct the TCP-style ports from the sockaddr structs */
  413.         local.in = (struct sockaddr_in *)up->name;
  414.         remote.in = (struct sockaddr_in *)up->peername;
  415.  
  416.         if(local.in->sin_addr.s_addr == INADDR_ANY)
  417.             /* Choose a local address */
  418.             local.in->sin_addr.s_addr =
  419.              locaddr(remote.in->sin_addr.s_addr);
  420.  
  421.         lsock.address = local.in->sin_addr.s_addr;
  422.         lsock.port = local.in->sin_port;
  423.         fsock.address = remote.in->sin_addr.s_addr;
  424.         fsock.port = remote.in->sin_port;
  425.  
  426.         /* Open the TCB in active mode */
  427.         up->cb.tcb = open_tcp(&lsock,&fsock,TCP_ACTIVE,0,
  428.          s_trcall,s_ttcall,s_tscall,0,s);
  429.  
  430.         /* Wait for the connection to complete */
  431.         while((cb.tcb = up->cb.tcb) != NULLTCB && cb.tcb->state != TCP_ESTABLISHED){
  432.             if(up->noblock){
  433.                 errno = EWOULDBLOCK;
  434.                 return -1;
  435.             } else if((errno = pwait(up)) != 0){
  436.                 return -1;
  437.             }
  438.         }
  439.         if(cb.tcb == NULLTCB){
  440.             /* Probably got refused */
  441.             free(up->peername);
  442.             up->peername = NULLCHAR;
  443.             errno = ECONNREFUSED;
  444.             return -1;
  445.         }
  446.         break;
  447.     case TYPE_UDP:
  448. #ifdef    AX25
  449.     case TYPE_AX25UI:
  450. #endif
  451. #ifdef    NETROM
  452.     case TYPE_NETROML3:
  453. #endif
  454.     case TYPE_RAW:
  455.         /* Control block already created by bind() */
  456.         break;
  457. #ifdef    AX25
  458.     case TYPE_AX25I:
  459.         local.ax = (struct sockaddr_ax *)up->name;
  460.         remote.ax = (struct sockaddr_ax *)up->peername;
  461.         if((iface = if_lookup(remote.ax->iface)) == NULLIF){
  462.             errno = EINVAL;
  463.             return -1;
  464.         }
  465.         if(local.ax->ax25_addr[0] == '\0'){
  466.             /* The local address was unspecified; set it from
  467.              * the interface address
  468.              */
  469.             memcpy(local.ax->ax25_addr,iface->hwaddr,AXALEN);
  470.         }
  471.         /* If we already have an AX25 link we can use it */
  472.         if((up->cb.ax25 = find_ax25(remote.ax->ax25_addr)) != NULLAX25
  473.            && up->cb.ax25->state != LAPB_DISCONNECTED &&
  474.            up->cb.ax25->user == -1) {
  475.             up->cb.ax25->user = s;
  476.             up->cb.ax25->r_upcall = s_arcall;
  477.             up->cb.ax25->t_upcall = s_atcall;
  478.             up->cb.ax25->s_upcall = s_ascall;
  479.             if(up->cb.ax25->state == LAPB_CONNECTED
  480.                || up->cb.ax25->state == LAPB_RECOVERY)
  481.                     return 0;
  482.         } else
  483.             up->cb.ax25 = open_ax25(iface,local.ax->ax25_addr,
  484.              remote.ax->ax25_addr,AX_ACTIVE,
  485.              Axwindow,s_arcall,s_atcall,s_ascall,s);
  486.  
  487.         /* Wait for the connection to complete */
  488.         while((cb.ax25 = up->cb.ax25) != NULLAX25 && cb.ax25->state != LAPB_CONNECTED){
  489.             if(up->noblock){
  490.                 errno = EWOULDBLOCK;
  491.                 return -1;
  492.             } else if((errno = pwait(up)) != 0){
  493.                 return -1;
  494.             }
  495.         }
  496.         if(cb.ax25 == NULLAX25){
  497.             /* Connection probably already exists */
  498.             free(up->peername);
  499.             up->peername = NULLCHAR;
  500.             errno = ECONNREFUSED;
  501.             return -1;
  502.         }
  503.         break;
  504. #endif
  505. #ifdef    NETROM
  506.     case TYPE_NETROML4:
  507.         local.nr = (struct sockaddr_nr *)up->name;
  508.         remote.nr = (struct sockaddr_nr *)up->peername;
  509.         up->cb.nr4 = open_nr4(&local.nr->nr_addr,&remote.nr->nr_addr,
  510.          AX_ACTIVE,s_nrcall,s_ntcall,s_nscall,s);
  511.  
  512.         /* Wait for the connection to complete */
  513.         while((cb.nr4 = up->cb.nr4) != NULLNR4CB && cb.nr4->state != NR4STCON){
  514.             if(up->noblock){
  515.                 errno = EWOULDBLOCK;
  516.                 return -1;
  517.             } else if((errno = pwait(up)) != 0){
  518.                 return -1;
  519.             }
  520.         }
  521.         if(cb.nr4 == NULLNR4CB){
  522.             /* Connection probably already exists */
  523.             free(up->peername);
  524.             up->peername = NULLCHAR;
  525.             errno = ECONNREFUSED;
  526.             return -1;
  527.         }
  528.         break;
  529. #endif
  530.     }
  531.     return 0;
  532. }
  533. /* Wait for a connection. Valid only for connection-oriented sockets. */
  534. int
  535. accept(s,peername,peernamelen)
  536. int s;            /* Socket index */
  537. char *peername;        /* Peer name */
  538. int *peernamelen;    /* Length of peer name */
  539. {
  540.     int i;
  541.     register struct usock *up;
  542.  
  543.     if((up = itop(s)) == NULLUSOCK){
  544.         errno = EBADF;
  545.         return -1;
  546.     }
  547.     if(up->type == TYPE_LOCAL_DGRAM || up->type == TYPE_LOCAL_STREAM){
  548.         errno = EINVAL;
  549.         return -1;
  550.     }
  551.     if(up->cb.p == NULLCHAR){
  552.         errno = EOPNOTSUPP;
  553.         return -1;
  554.     }
  555.     /* Accept is valid only for stream sockets */
  556.     switch(up->type){
  557.     case TYPE_TCP:
  558. #ifdef    AX25
  559.     case TYPE_AX25I:
  560. #endif
  561. #ifdef    NETROM
  562.     case TYPE_NETROML4:
  563. #endif
  564.         break;
  565.     default:
  566.         errno = EOPNOTSUPP;
  567.         return -1;
  568.     }    
  569.     /* Wait for the state-change upcall routine to signal us */
  570.     while(up->cb.p != NULLCHAR && up->rdysock == -1){
  571.         if(up->noblock){
  572.             errno = EWOULDBLOCK;
  573.             return -1;
  574.         } else if((errno = pwait(up)) != 0){
  575.             return -1;
  576.         }
  577.     }
  578.     if(up->cb.p == NULLCHAR){
  579.         /* Blown away */
  580.         errno = EBADF;
  581.         return -1;
  582.     }
  583.     i = up->rdysock;
  584.     up->rdysock = -1;
  585.  
  586.     up = &Usock[i];
  587.     if(peername != NULLCHAR && peernamelen != NULL){
  588.         *peernamelen = min(up->peernamelen,*peernamelen);
  589.         memcpy(peername,up->peername,*peernamelen);
  590.     }
  591.     return i;
  592. }
  593. /* Low-level receive routine. Passes mbuf back to user; more efficient than
  594.  * higher-level functions recv() and recvfrom(). Datagram sockets ignore
  595.  * the len parameter.
  596.  */
  597. int
  598. recv_mbuf(s,bpp,flags,from,fromlen)
  599. int s;            /* Socket index */
  600. struct mbuf **bpp;    /* Place to stash receive buffer */
  601. int flags;        /* Unused; will control out-of-band data, etc */
  602. char *from;        /* Peer address (only for datagrams) */
  603. int *fromlen;        /* Length of peer address */
  604. {
  605.     register struct usock *up;
  606.     int cnt;
  607.     union cb cb;
  608.     struct socket fsocket;
  609. #ifdef    NETROM
  610.     struct nr3hdr n3hdr;
  611. #endif
  612.     union sp remote;
  613.     struct ip ip;
  614.     struct mbuf *bp;
  615.  
  616.     if((up = itop(s)) == NULLUSOCK){
  617.         errno = EBADF;
  618.         return -1;
  619.     }
  620.     if(up->ibuf != NULLBUF){
  621.         /* Return input buffer */
  622.         cnt = len_p(up->ibuf);
  623.         if(bpp != NULLBUFP)
  624.             *bpp = up->ibuf;
  625.         else
  626.             free_p(up->ibuf);
  627.         up->ibuf = NULLBUF;        
  628.         return cnt;
  629.     }
  630.     switch(up->type){
  631.     case TYPE_LOCAL_STREAM:
  632.     case TYPE_LOCAL_DGRAM:
  633.         while(up->cb.local != NULLLOC && up->cb.local->q == NULLBUF){
  634.             if(up->noblock){
  635.                 errno = EWOULDBLOCK;
  636.                 return -1;
  637.             } else if((errno = pwait(up)) != 0){
  638.                 return -1;
  639.             }
  640.         }
  641.         if(up->cb.local == NULLLOC){
  642.             errno = EBADF;
  643.             return -1;
  644.         }
  645.         /* For datagram sockets, this will return the
  646.          * first packet on the queue. For stream sockets,
  647.          * this will return everything.
  648.          */
  649.         bp = dequeue(&up->cb.local->q);
  650.         if(up->cb.local->q == NULLBUF
  651.          && (up->cb.local->flags & LOC_SHUTDOWN))
  652.             close_s(s);
  653.         psignal(up,0);
  654.         cnt = len_p(bp);
  655.         break;
  656.     case TYPE_TCP:
  657.         while((cb.tcb = up->cb.tcb) != NULLTCB
  658.          && cb.tcb->r_upcall != trdiscard
  659.                  && (cnt = recv_tcp(cb.tcb,&bp,(int16)0)) == -1){
  660.             if(up->noblock){
  661.                 errno = EWOULDBLOCK;
  662.                 return -1;
  663.             } else if((errno = pwait(up)) != 0){
  664.                 return -1;
  665.             }
  666.         }
  667.         if(cb.tcb == NULLTCB){
  668.             /* Connection went away */
  669.             errno = ENOTCONN;
  670.             return -1;
  671.         } else if(cb.tcb->r_upcall == trdiscard){
  672.             /* Receive shutdown has been done */
  673.             errno = ENOTCONN;    /* CHANGE */
  674.             return -1;
  675.         }
  676.         break;
  677.     case TYPE_UDP:
  678.         while((cb.udp = up->cb.udp) != NULLUDP
  679.         && (cnt = recv_udp(cb.udp,&fsocket,&bp)) == -1){
  680.             if(up->noblock){
  681.                 errno = EWOULDBLOCK;
  682.                 return -1;
  683.             } else if((errno = pwait(up)) != 0){
  684.                 return -1;
  685.             }
  686.         }
  687.         if(cb.udp == NULLUDP){
  688.             /* Connection went away */
  689.             errno = ENOTCONN;
  690.             return -1;
  691.         }
  692.         if(from != NULLCHAR && fromlen != (int *)NULL && *fromlen >= SOCKSIZE){
  693.             remote.in = (struct sockaddr_in *)from;
  694.             remote.in->sin_family = AF_INET;
  695.             remote.in->sin_addr.s_addr = fsocket.address;
  696.             remote.in->sin_port = fsocket.port;
  697.             *fromlen = SOCKSIZE;
  698.         }
  699.         break;
  700.     case TYPE_RAW:
  701.         while((cb.rip = up->cb.rip) != NULLRIP
  702.          && cb.rip->rcvq == NULLBUF){
  703.             if(up->noblock){
  704.                 errno = EWOULDBLOCK;
  705.                 return -1;
  706.             } else if((errno = pwait(up)) != 0){
  707.                 return -1;
  708.             }
  709.         }
  710.         if(cb.rip == NULLRIP){
  711.             /* Connection went away */
  712.             errno = ENOTCONN;
  713.             return -1;
  714.         }
  715.         bp = dequeue(&cb.rip->rcvq);
  716.         ntohip(&ip,&bp);
  717.         cnt = len_p(bp);
  718.         if(from != NULLCHAR && fromlen != (int *)NULL && *fromlen >= SOCKSIZE){
  719.             remote.in = (struct sockaddr_in *)from;
  720.             remote.in->sin_family = AF_INET;
  721.             remote.in->sin_addr.s_addr = ip.source;
  722.             remote.in->sin_port = 0;
  723.             *fromlen = SOCKSIZE;
  724.         }
  725.         break;
  726. #ifdef    AX25
  727.     case TYPE_AX25I:
  728.         while((cb.ax25 = up->cb.ax25) != NULLAX25
  729.          && (bp = recv_ax25(cb.ax25,(int16)0)) == NULLBUF){
  730.             if(up->noblock){
  731.                 errno = EWOULDBLOCK;
  732.                 return -1;
  733.             } else if((errno = pwait(up)) != 0){
  734.                 return -1;
  735.             }
  736.         }
  737.         if(cb.ax25 == NULLAX25){
  738.             /* Connection went away */
  739.             errno = ENOTCONN;
  740.             return -1;
  741.         }
  742.         cnt = bp->cnt;
  743.         break;
  744.     case TYPE_AX25UI:
  745.         while(s == Axui_sock && Bcq == NULLBUF){
  746.             if(up->noblock){
  747.                 errno = EWOULDBLOCK;
  748.                 return -1;
  749.             } else if((errno = pwait(&Bcq)) != 0){
  750.                 return -1;
  751.             }
  752.         }
  753.         if(s != Axui_sock){
  754.             errno = ENOTCONN;
  755.             return -1;
  756.         }
  757.         bp = dequeue(&Bcq);
  758.  
  759.         if(from != NULLCHAR && fromlen != NULLINT
  760.            && *fromlen >= sizeof(struct sockaddr_ax)){
  761.             pullup(&bp,from,sizeof(struct sockaddr_ax));
  762.             *fromlen = sizeof(struct sockaddr_ax);
  763.         } else {
  764.             pullup(&bp,NULLCHAR,sizeof(struct sockaddr_ax));
  765.         }
  766.         cnt = len_p(bp);
  767.         break;
  768. #endif
  769. #ifdef NETROM
  770.     case TYPE_NETROML3:
  771.         while((cb.rnr = up->cb.rnr) != NULLRNR
  772.          && cb.rnr->rcvq == NULLBUF){
  773.             if(up->noblock){
  774.                 errno = EWOULDBLOCK;
  775.                 return -1;
  776.             } else if((errno = pwait(up)) != 0){
  777.                 return -1;
  778.             }
  779.         }
  780.         if(cb.rnr == NULLRNR){
  781.             /* Connection went away */
  782.             errno = ENOTCONN;
  783.             return -1;
  784.         }
  785.         bp = dequeue(&cb.rnr->rcvq);
  786.         ntohnr3(&n3hdr,&bp);
  787.         cnt = len_p(bp);
  788.         if(from != NULLCHAR && fromlen != NULLINT
  789.            && *fromlen >= sizeof(struct sockaddr_nr)){
  790.             remote.nr = (struct sockaddr_nr *)from;
  791.             remote.nr->nr_family = AF_NETROM;
  792.             /* The callsign of the local user is not part of
  793.                NET/ROM level 3, so that field is not used here */
  794.             memcpy(remote.nr->nr_addr.node,n3hdr.source,AXALEN);
  795.             *fromlen = sizeof(struct sockaddr_nr);
  796.         }
  797.         break;
  798.     case TYPE_NETROML4:
  799.         while((cb.nr4 = up->cb.nr4) != NULLNR4CB
  800.          && (bp = recv_nr4(cb.nr4,(int16)0)) == NULLBUF){
  801.             if(up->noblock){
  802.                 errno = EWOULDBLOCK;
  803.                 return -1;
  804.             } else if((errno = pwait(up)) != 0){
  805.                 return -1;
  806.             }
  807.         }
  808.         if(cb.nr4 == NULLNR4CB){
  809.             /* Connection went away */
  810.             errno = ENOTCONN;
  811.             return -1;
  812.         }
  813.         cnt = bp->cnt;
  814.         break;
  815. #endif
  816.     }
  817.     if(bpp != NULLBUFP)
  818.         *bpp = bp;
  819.     else
  820.         free_p(bp);
  821.     return cnt;
  822. }
  823. /* Low level send routine; user supplies mbuf for transmission. More
  824.  * efficient than send() or sendto(), the higher level interfaces.
  825.  * The "to" and "tolen" parameters are ignored on connection-oriented
  826.  * sockets.
  827.  *
  828.  * In case of error, bp is freed so the caller doesn't have to worry about it.
  829.  */
  830. int
  831. send_mbuf(s,bp,flags,to,tolen)
  832. int s;            /* Socket index */
  833. struct mbuf *bp;    /* Buffer to send */
  834. int flags;        /* not currently used */
  835. char *to;        /* Destination, only for datagrams */
  836. int tolen;        /* Length of destination */
  837. {
  838.     register struct usock *up;
  839.     union cb cb;
  840.     union sp local,remote;
  841.     struct socket lsock,fsock;
  842.     int cnt;
  843.  
  844.     if((up = itop(s)) == NULLUSOCK){
  845.         free_p(bp);
  846.         errno = EBADF;
  847.         return -1;
  848.     }
  849. #ifndef    notdef
  850.     if(up->obuf != NULLBUF){
  851.         /* If there's unflushed output, send it.
  852.          * Note the importance of clearing up->obuf
  853.          * before the recursive call!
  854.          */
  855.         struct mbuf *bp1;
  856.  
  857.         bp1 = up->obuf;
  858.         up->obuf = NULLBUF;
  859.         send_mbuf(s,bp1,flags,to,tolen);
  860.     }
  861. #endif
  862.     if(up->name == NULLCHAR){
  863.         /* Automatic local name assignment for datagram sockets */
  864.         switch(up->type){
  865.         case TYPE_LOCAL_STREAM:
  866.         case TYPE_LOCAL_DGRAM:
  867.             break;    /* no op */
  868.         case TYPE_UDP:
  869.         case TYPE_RAW:
  870.             autobind(s,AF_INET);
  871.             break;
  872. #ifdef    AX25
  873.         case TYPE_AX25UI:
  874.             autobind(s,AF_AX25);
  875.             break;
  876. #endif
  877. #ifdef    NETROM
  878.         case TYPE_NETROML3:
  879.         case TYPE_NETROML4:
  880.             autobind(s,AF_NETROM);
  881.             break;
  882. #endif
  883.         default:
  884.             free_p(bp);
  885.             errno = ENOTCONN;
  886.             return -1;
  887.         }
  888.     }
  889.     cnt = len_p(bp);
  890.     switch(up->type){
  891.     case TYPE_LOCAL_DGRAM:
  892.         enqueue(&up->cb.local->q,bp);
  893.         psignal(up,0);
  894.         /* If high water mark has been reached, block */
  895.         while(len_q(up->cb.local->q) >= up->cb.local->hiwat){
  896.             if(up->noblock){
  897.                 errno = EWOULDBLOCK;
  898.                 return -1;
  899.             } else if((errno = pwait(up)) != 0){
  900.                 return -1;
  901.             }
  902.         }
  903.         break;
  904.     case TYPE_LOCAL_STREAM:
  905.         append(&up->cb.local->q,bp);
  906.         psignal(up,0);
  907.         /* If high water mark has been reached, block */
  908.         while(len_p(up->cb.local->q) >= up->cb.local->hiwat){
  909.             if(up->noblock){
  910.                 errno = EWOULDBLOCK;
  911.                 return -1;
  912.             } else if((errno = pwait(up)) != 0){
  913.                 return -1;
  914.             }
  915.         }
  916.         break;
  917.     case TYPE_TCP:
  918.         if((cb.tcb = up->cb.tcb) == NULLTCB){
  919.             free_p(bp);
  920.             errno = ENOTCONN;
  921.             return -1;
  922.         }        
  923.         cnt = send_tcp(cb.tcb,bp);
  924.  
  925.         while((cb.tcb = up->cb.tcb) != NULLTCB &&
  926.          cb.tcb->sndcnt > cb.tcb->window){
  927.             /* Send queue is full */
  928.             if(up->noblock){
  929.                 errno = EWOULDBLOCK;
  930.                 return -1;
  931.             } else if((errno = pwait(up)) != 0){
  932.                 return -1;
  933.             }
  934.         }
  935.          if(cb.tcb == NULLTCB){
  936.             errno = ENOTCONN;
  937.             return -1;
  938.         }
  939.         break;
  940.     case TYPE_UDP:
  941.         local.in = (struct sockaddr_in *)up->name;
  942.         lsock.address = local.in->sin_addr.s_addr;
  943.         lsock.port = local.in->sin_port;
  944.         if(to != NULLCHAR)
  945.             remote.in = (struct sockaddr_in *)to;
  946.         else if(up->peername != NULLCHAR)
  947.             remote.in = (struct sockaddr_in *)up->peername;
  948.         else {
  949.             errno = ENOTCONN;
  950.             return -1;
  951.         }    
  952.         fsock.address = remote.in->sin_addr.s_addr;
  953.         fsock.port = remote.in->sin_port;
  954.         send_udp(&lsock,&fsock,0,0,bp,0,0,0);
  955.         break;
  956.     case TYPE_RAW:
  957.         local.in = (struct sockaddr_in *)up->name;
  958.         if(to != NULLCHAR)
  959.             remote.in = (struct sockaddr_in *)to;
  960.         else if(up->peername != NULLCHAR)
  961.             remote.in = (struct sockaddr_in *)up->peername;
  962.         else {
  963.             errno = ENOTCONN;
  964.             return -1;
  965.         }    
  966.         ip_send(local.in->sin_addr.s_addr,remote.in->sin_addr.s_addr,
  967.             (char)up->cb.rip->protocol,0,0,bp,0,0,0);
  968.         break;
  969. #ifdef    AX25
  970.     case TYPE_AX25I:
  971.         if((cb.ax25 = up->cb.ax25) == NULLAX25){
  972.             free_p(bp);
  973.             errno = ENOTCONN;
  974.             return -1;
  975.         }
  976.         send_ax25(cb.ax25,bp,PID_NO_L3);
  977.  
  978.         while((cb.ax25 = up->cb.ax25) != NULLAX25 &&
  979.          len_q(cb.ax25->txq) * cb.ax25->paclen > cb.ax25->window){
  980.             if(up->noblock){
  981.                 errno = EWOULDBLOCK;
  982.                 return -1;
  983.             } else if((errno = pwait(up)) != 0){
  984.                 return -1;
  985.             }
  986.         }
  987.         if(cb.ax25 == NULLAX25){
  988.             errno = EBADF;
  989.             return -1;
  990.         }
  991.         break;
  992.     case TYPE_AX25UI:
  993.         local.ax = (struct sockaddr_ax *)up->name;
  994.         if(to != NULLCHAR)
  995.             remote.ax = (struct sockaddr_ax *)to;
  996.         else if(up->peername != NULLCHAR)
  997.             remote.ax = (struct sockaddr_ax *)up->peername;
  998.         else {
  999.             errno = ENOTCONN;
  1000.             return -1;
  1001.         }
  1002.         ax_output(if_lookup(remote.ax->iface),
  1003.               remote.ax->ax25_addr,
  1004.               local.ax->ax25_addr,PID_NO_L3,bp);
  1005.         break;
  1006. #endif
  1007. #ifdef NETROM
  1008.     case TYPE_NETROML3:
  1009.         if(len_p(bp) > NR4MAXINFO) {
  1010.             free_p(bp);
  1011.             errno = EMSGSIZE;
  1012.             return -1;
  1013.         }
  1014.         local.nr = (struct sockaddr_nr *)up->name;
  1015.         if(to != NULLCHAR)
  1016.             remote.nr = (struct sockaddr_nr *)to;
  1017.         else if(up->peername != NULLCHAR)
  1018.             remote.nr = (struct sockaddr_nr *)up->peername;
  1019.         else {
  1020.             errno = ENOTCONN;
  1021.             return -1;
  1022.         }    
  1023.         /* The NETROM username is always ignored in outgoing traffic */
  1024.         nr_sendraw(remote.nr->nr_addr.node,
  1025.          up->cb.rnr->protocol,up->cb.rnr->protocol,bp);
  1026.         break;
  1027.     case TYPE_NETROML4:
  1028.         if((cb.nr4 = up->cb.nr4) == NULLNR4CB) {
  1029.             free_p(bp);
  1030.             errno = ENOTCONN;
  1031.             return -1;
  1032.         }
  1033.         if(len_p(bp) > NR4MAXINFO){ /* reject big packets */
  1034.             free_p(bp);
  1035.             errno = EMSGSIZE;
  1036.             return -1;
  1037.         }
  1038.         send_nr4(cb.nr4,bp);
  1039.  
  1040.         while((cb.nr4 = up->cb.nr4) != NULLNR4CB &&
  1041.          cb.nr4->nbuffered >= cb.nr4->window){
  1042.             if(up->noblock){
  1043.                 errno = EWOULDBLOCK;
  1044.                 return -1;
  1045.             } else if((errno = pwait(up)) != 0){
  1046.                 errno = EINTR;
  1047.                 return -1;
  1048.             }
  1049.         }
  1050.         if(cb.nr4 == NULLNR4CB){
  1051.             errno = EBADF;
  1052.             return -1;
  1053.         }
  1054.         break;
  1055. #endif
  1056.     }    
  1057.     return cnt;
  1058. }
  1059. /* Return local name passed in an earlier bind() call */
  1060. int
  1061. getsockname(s,name,namelen)
  1062. int s;        /* Socket index */
  1063. char *name;    /* Place to stash name */
  1064. int *namelen;    /* Length of same */
  1065. {
  1066.     register struct usock *up;
  1067.  
  1068.     if((up = itop(s)) == NULLUSOCK){
  1069.         errno = EBADF;
  1070.         return -1;
  1071.     }
  1072.     if(name == NULLCHAR || namelen == (int *)NULL){
  1073.         errno = EFAULT;
  1074.         return -1;
  1075.     }
  1076.     if(up->name == NULLCHAR){
  1077.         /* Not bound yet */
  1078.         *namelen = 0;
  1079.         return 0;
  1080.     }
  1081.     if(up->name != NULLCHAR){
  1082.         *namelen = min(*namelen,up->namelen);
  1083.         memcpy(name,up->name,*namelen);
  1084.     }
  1085.     return 0;
  1086. }
  1087. /* Get remote name, returning result of earlier connect() call. */
  1088. int
  1089. getpeername(s,peername,peernamelen)
  1090. int s;            /* Socket index */
  1091. char *peername;        /* Place to stash name */
  1092. int *peernamelen;    /* Length of same */
  1093. {
  1094.     register struct usock *up;
  1095.  
  1096.     if((up = itop(s)) == NULLUSOCK){
  1097.         errno = EBADF;
  1098.         return -1;
  1099.     }
  1100.     if(up->peername == NULLCHAR){
  1101.         errno = ENOTCONN;
  1102.         return -1;
  1103.     }
  1104.     if(peername == NULLCHAR || peernamelen == (int *)NULL){
  1105.         errno = EFAULT;
  1106.         return -1;
  1107.     }
  1108.     *peernamelen = min(*peernamelen,up->peernamelen);
  1109.     memcpy(peername,up->peername,*peernamelen);
  1110.     return 0;
  1111. }
  1112. /* Return length of protocol queue, either send or receive. */
  1113. int
  1114. socklen(s,rtx)
  1115. int s;        /* Socket index */
  1116. int rtx;    /* 0 = receive queue, 1 = transmit queue */
  1117. {
  1118.     register struct usock *up;
  1119.     int len = -1;
  1120.  
  1121.     if((up = itop(s)) == NULLUSOCK){
  1122.         errno = EBADF;
  1123.         return -1;
  1124.     }
  1125.     if(up->cb.p == NULLCHAR){
  1126.         errno = ENOTCONN;
  1127.         return -1;
  1128.     }
  1129.     if(rtx < 0 || rtx > 1){
  1130.         errno = EINVAL;
  1131.         return -1;
  1132.     }
  1133.     switch(up->type){
  1134.     case TYPE_LOCAL_DGRAM:
  1135.         len = len_q(up->cb.local->q);
  1136.         break;
  1137.     case TYPE_LOCAL_STREAM:
  1138.         len = len_p(up->cb.local->q)
  1139.          + len_p(up->ibuf) + len_p(up->obuf);
  1140.         break;
  1141.     case TYPE_TCP:
  1142.         switch(rtx){
  1143.         case 0:
  1144.             len = up->cb.tcb->rcvcnt + len_p(up->ibuf);
  1145.             break;
  1146.         case 1:
  1147.             len = up->cb.tcb->sndcnt + len_p(up->obuf);
  1148.             break;
  1149.         }
  1150.         break;
  1151.     case TYPE_UDP:
  1152.         switch(rtx){
  1153.         case 0:
  1154.             len = up->cb.udp->rcvcnt;
  1155.             break;
  1156.         case 1:
  1157.             len = 0;
  1158.             break;
  1159.         }
  1160.         break;
  1161. #ifdef    AX25
  1162.     case TYPE_AX25I:
  1163.         switch(rtx){
  1164.         case 0:
  1165.             len = len_p(up->cb.ax25->rxq) + len_p(up->ibuf);
  1166.             break;
  1167.         case 1:    /* Number of packets, not bytes */
  1168.             len = len_q(up->cb.ax25->txq);
  1169.             if(up->obuf != NULLBUF)
  1170.                 len++;
  1171.         }
  1172.         break;
  1173.     case TYPE_AX25UI:
  1174.         switch(rtx){    
  1175.         case 0:
  1176.             len = len_q(Bcq);
  1177.             break;
  1178.         case 1:
  1179.             len = 0;        
  1180.             break;
  1181.         }
  1182.         break;
  1183. #endif
  1184. #ifdef NETROM
  1185.     case TYPE_NETROML3:
  1186.         switch(rtx){    
  1187.         case 0:
  1188.             len = len_q(up->cb.rnr->rcvq);
  1189.             break;
  1190.         case 1:
  1191.             len = 0;        
  1192.         }
  1193.         break;
  1194.     case TYPE_NETROML4:
  1195.         switch(rtx){
  1196.         case 0:
  1197.             len = len_p(up->cb.nr4->rxq) + len_p(up->obuf);
  1198.             break;
  1199.         case 1:    /* Number of packets, not bytes */
  1200.             len = len_q(up->cb.nr4->txq);
  1201.             if(up->obuf != NULLBUF)
  1202.                 len++;
  1203.             break;
  1204.         }
  1205.         break;
  1206. #endif
  1207.     case TYPE_RAW:
  1208.         switch(rtx){    
  1209.         case 0:
  1210.             len = len_q(up->cb.rip->rcvq);
  1211.             break;
  1212.         case 1:
  1213.             len = 0;        
  1214.             break;
  1215.         }
  1216.         break;
  1217.     }
  1218.     return len;
  1219. }
  1220. /* Force retransmission. Valid only for connection-oriented sockets. */
  1221. int
  1222. sockkick(s)
  1223. int s;    /* Socket index */
  1224. {
  1225.     register struct usock *up;
  1226.  
  1227.     if((up = itop(s)) == NULLUSOCK){
  1228.         errno = EBADF;
  1229.         return -1;
  1230.     }
  1231.     if(up->type == TYPE_LOCAL_STREAM || up->type == TYPE_LOCAL_DGRAM){
  1232.         errno = EINVAL;
  1233.         return -1;
  1234.     }
  1235.     if(up->cb.p == NULLCHAR){
  1236.         errno = ENOTCONN;
  1237.         return -1;
  1238.     }
  1239.     switch(up->type){
  1240.     case TYPE_TCP:
  1241.         kick_tcp(up->cb.tcb);
  1242.         break;
  1243. #ifdef    AX25
  1244.     case TYPE_AX25I:
  1245.         kick_ax25(up->cb.ax25);
  1246.         break;
  1247. #endif
  1248. #ifdef NETROM
  1249.     case TYPE_NETROML4:
  1250.         kick_nr4(up->cb.nr4);
  1251.         break;
  1252. #endif
  1253.     default:
  1254.         /* Datagram sockets can't be kicked */
  1255.         errno = EOPNOTSUPP;
  1256.         return -1;
  1257.     }
  1258.     return 0;
  1259. }
  1260.  
  1261. /* Change owner of socket, return previous owner */
  1262. struct proc *
  1263. sockowner(s,newowner)
  1264. int s;            /* Socket index */
  1265. struct proc *newowner;    /* Process table address of new owner */
  1266. {
  1267.     register struct usock *up;
  1268.     struct proc *pp;
  1269.  
  1270.     if((up = itop(s)) == NULLUSOCK){
  1271.         errno = EBADF;
  1272.         return NULLPROC;
  1273.     }
  1274.     pp = up->owner;
  1275.     if(newowner != NULLPROC)
  1276.         up->owner = newowner;
  1277.     return pp;
  1278. }
  1279. /* Close down a socket three ways. Type 0 means "no more receives"; this
  1280.  * replaces the incoming data upcall with a routine that discards further
  1281.  * data. Type 1 means "no more sends", and obviously corresponds to sending
  1282.  * a TCP FIN. Type 2 means "no more receives or sends". This I interpret
  1283.  * as "abort the connection".
  1284.  */
  1285. int
  1286. shutdown(s,how)
  1287. int s;        /* Socket index */
  1288. int how;    /* (see above) */
  1289. {
  1290.     register struct usock *up;
  1291.  
  1292.     if((up = itop(s)) == NULLUSOCK){
  1293.         errno = EBADF;
  1294.         return -1;
  1295.     }
  1296.     if(up->cb.p == NULLCHAR){
  1297.         errno = ENOTCONN;
  1298.         return -1;
  1299.     }
  1300.     switch(up->type){
  1301.     case TYPE_LOCAL_DGRAM:
  1302.     case TYPE_LOCAL_STREAM:
  1303.         if(up->cb.local->q == NULLBUF)
  1304.             close_s(s);
  1305.         else
  1306.             up->cb.local->flags = LOC_SHUTDOWN;
  1307.         break;
  1308.     case TYPE_TCP:
  1309.         switch(how){
  1310.         case 0:    /* No more receives -- replace upcall */
  1311.             up->cb.tcb->r_upcall = trdiscard;
  1312.             break;
  1313.         case 1:    /* Send EOF */
  1314.             close_tcp(up->cb.tcb);
  1315.             break;
  1316.         case 2:    /* Blow away TCB */
  1317.             reset_tcp(up->cb.tcb);
  1318.             up->cb.tcb = NULLTCB;
  1319.             break;
  1320.         }
  1321.         break;
  1322. #ifdef    AX25
  1323.     case TYPE_AX25UI:
  1324.         close_s(s);
  1325.         break;
  1326.     case TYPE_AX25I:
  1327.         switch(how){
  1328.         case 0:
  1329.         case 1:    /* Attempt regular disconnect */
  1330.             disc_ax25(up->cb.ax25);
  1331.             break;
  1332.         case 2: /* Blow it away */
  1333.             reset_ax25(up->cb.ax25);
  1334.             up->cb.ax25 = NULLAX25;
  1335.             break;
  1336.         }
  1337.         break;        
  1338. #endif
  1339. #ifdef    NETROM
  1340.     case TYPE_NETROML3:
  1341.         close_s(s);
  1342.         break;
  1343.     case TYPE_NETROML4:
  1344.         switch(how){
  1345.         case 0:
  1346.         case 1:    /* Attempt regular disconnect */
  1347.             disc_nr4(up->cb.nr4);
  1348.             break;
  1349.         case 2: /* Blow it away */
  1350.             reset_nr4(up->cb.nr4);
  1351.             up->cb.nr4 = NULLNR4CB;
  1352.             break;
  1353.         }
  1354.         break;        
  1355. #endif
  1356.     case TYPE_RAW:
  1357.         close_s(s);
  1358.         break;
  1359.     default:
  1360.         errno = EOPNOTSUPP;
  1361.         return -1;
  1362.     }
  1363.     psignal(up,0);
  1364.     return 0;
  1365. }
  1366. /* Close a socket, freeing it for reuse. Try to do a graceful close on a
  1367.  * TCP socket, if possible
  1368.  */
  1369. int
  1370. close_s(s)
  1371. int s;        /* Socket index */
  1372. {
  1373.     register struct usock *up;
  1374.  
  1375.     if((up = itop(s)) == NULLUSOCK){
  1376.         errno = EBADF;
  1377.         return -1;
  1378.     }
  1379.     if(--up->refcnt > 0)
  1380.         return 0;    /* Others are still using it */
  1381.     usflush(s);
  1382.     if(up->ibuf != NULLBUF){
  1383.         free_p(up->ibuf);
  1384.         up->ibuf = NULLBUF;
  1385.     }
  1386.     switch(up->type){
  1387.     case TYPE_LOCAL_STREAM:
  1388.     case TYPE_LOCAL_DGRAM:
  1389.         free_q(&up->cb.local->q);
  1390.         free(up->cb.local);
  1391.         break;
  1392.     case TYPE_TCP:
  1393.         if(up->cb.tcb != NULLTCB){    /* In case it's been reset */
  1394.             up->cb.tcb->r_upcall = trdiscard;
  1395.             /* Tell the TCP_CLOSED upcall there's no more socket */
  1396.             up->cb.tcb->user = -1;
  1397.             close_tcp(up->cb.tcb);
  1398.         }
  1399.         break;
  1400.     case TYPE_UDP:
  1401.         if(up->cb.udp != NULLUDP){
  1402.             del_udp(up->cb.udp);
  1403.         }
  1404.         break;
  1405. #ifdef    AX25
  1406.     case TYPE_AX25I:
  1407.         if(up->cb.ax25 != NULLAX25){
  1408.             /* Tell the TCP_CLOSED upcall there's no more socket */
  1409.             up->cb.ax25->user = -1;
  1410.             disc_ax25(up->cb.ax25);
  1411.         }
  1412.         break;
  1413.     case TYPE_AX25UI:
  1414.         Axui_sock = -1;
  1415.         free_q(&Bcq);
  1416.         psignal(&Bcq,0);    /* Unblock any reads */
  1417.         break;
  1418. #endif
  1419. #ifdef    NETROM
  1420.     case TYPE_NETROML3:
  1421.         del_rnr(up->cb.rnr);
  1422.         break;
  1423.     case TYPE_NETROML4:
  1424.         if(up->cb.nr4 != NULLNR4CB){
  1425.             /* Tell the TCP_CLOSED upcall there's no more socket */
  1426.             up->cb.nr4->user = -1;
  1427.             disc_nr4(up->cb.nr4);
  1428.         }
  1429.         break;
  1430. #endif
  1431.     case TYPE_RAW:
  1432.         del_ip(up->cb.rip);
  1433.         break;
  1434.     default:
  1435.         errno = EOPNOTSUPP;
  1436.         return -1;
  1437.     }
  1438.     free(up->name);
  1439.     free(up->peername);
  1440.  
  1441.     up->cb.p = NULLCHAR;
  1442.     up->name = up->peername = NULLCHAR;
  1443.     up->type = NOTUSED;
  1444.     psignal(up,0);    /* Wake up anybody doing an accept() or recv() */
  1445.     return 0;
  1446. }
  1447. /* Increment reference count for specified socket */
  1448. int
  1449. usesock(s)
  1450. int s;
  1451. {
  1452.     struct usock *up;
  1453.  
  1454.     if((up = itop(s)) == NULLUSOCK){
  1455.         errno = EBADF;
  1456.         return -1;
  1457.     }
  1458.     up->refcnt++;
  1459.     return 0;
  1460. }
  1461. /* Blow away all sockets belonging to a certain process. Used by killproc(). */
  1462. void
  1463. freesock(pp)
  1464. struct proc *pp;
  1465. {
  1466.     register struct usock *up;
  1467.     register int i;
  1468.  
  1469.     for(i=0;i < Nusock;i++){
  1470.         up = &Usock[i];
  1471.         if(up->type != NOTUSED && up->owner == pp)
  1472.             shutdown(i,2);
  1473.     }
  1474. }
  1475. /* Start of internal subroutines */
  1476.  
  1477. /* Raw IP receive upcall routine */
  1478. static void
  1479. rip_recv(rp)
  1480. struct raw_ip *rp;
  1481. {
  1482.     psignal(itop(rp->user),1);
  1483.     pwait(NULL);
  1484. }
  1485.  
  1486. /* UDP receive upcall routine */
  1487. static void
  1488. s_urcall(iface,udp,cnt)
  1489. struct iface *iface;
  1490. struct udp_cb *udp;
  1491. int cnt;
  1492. {
  1493.     psignal(itop(udp->user),1);
  1494.     pwait(NULL);
  1495. }
  1496. /* TCP receive upcall routine */
  1497. static void
  1498. s_trcall(tcb,cnt)
  1499. struct tcb *tcb;
  1500. int cnt;
  1501. {
  1502.     /* Wake up anybody waiting for data, and let them run */
  1503.     psignal(itop(tcb->user),1);
  1504.     pwait(NULL);
  1505. }
  1506. /* TCP transmit upcall routine */
  1507. static void
  1508. s_ttcall(tcb,cnt)
  1509. struct tcb *tcb;
  1510. int cnt;
  1511. {
  1512.     /* Wake up anybody waiting to send data, and let them run */
  1513.     psignal(itop(tcb->user),1);
  1514.     pwait(NULL);
  1515. }
  1516. /* TCP state change upcall routine */
  1517. static void
  1518. s_tscall(tcb,old,new)
  1519. struct tcb *tcb;
  1520. int old,new;
  1521. {
  1522.     int s,ns;
  1523.     struct usock *up,*nup,*oup;
  1524.     union sp sp;
  1525.  
  1526.     s = tcb->user;
  1527.     oup = up = itop(s);
  1528.  
  1529.     switch(new){
  1530.     case TCP_CLOSED:
  1531.         /* Clean up. If the user has already closed the socket,
  1532.          * then up will be null (s was set to -1 by the close routine).
  1533.          * If not, then this is an abnormal close (e.g., a reset)
  1534.          * and clearing out the pointer in the socket structure will
  1535.          * prevent any further operations on what will be a freed
  1536.          * control block. Also wake up anybody waiting on events
  1537.          * related to this tcb so they will notice it disappearing.
  1538.          */
  1539.         if(up != NULLUSOCK){
  1540.             up->cb.tcb = NULLTCB;
  1541.             up->errcodes[0] = tcb->reason;
  1542.             up->errcodes[1] = tcb->type;
  1543.             up->errcodes[2] = tcb->code;
  1544.         }
  1545.         del_tcp(tcb);
  1546.         break;
  1547.     case TCP_SYN_RECEIVED:
  1548.         /* Handle an incoming connection. If this is a server TCB,
  1549.          * then we're being handed a "clone" TCB and we need to
  1550.          * create a new socket structure for it. In either case,
  1551.          * find out who we're talking to and wake up the guy waiting
  1552.          * for the connection.
  1553.          */
  1554.         if(tcb->flags.clone){
  1555.             /* Clone the socket */
  1556.             ns = socket(AF_INET,SOCK_STREAM,0);
  1557.             nup = &Usock[ns];
  1558.             ASSIGN(*nup,*up);
  1559.             tcb->user = ns;
  1560.             nup->cb.tcb = tcb;
  1561.             /* Allocate new memory for the name areas */
  1562.             nup->name = mallocw(SOCKSIZE);
  1563.             nup->peername = mallocw(SOCKSIZE);
  1564.             /* Store the new socket # in the old one */
  1565.             up->rdysock = ns;
  1566.             up = nup;
  1567.             s = ns;
  1568.         } else {
  1569.             /* Allocate space for the peer's name */
  1570.             up->peername = mallocw(SOCKSIZE);
  1571.             /* Store the old socket # in the old socket */
  1572.             up->rdysock = s;
  1573.         }
  1574.         /* Load the addresses. Memory for the name has already
  1575.          * been allocated, either above or in the original bind.
  1576.          */
  1577.         sp.p = up->name;
  1578.         sp.in->sin_family = AF_INET;
  1579.         sp.in->sin_addr.s_addr = up->cb.tcb->conn.local.address;
  1580.         sp.in->sin_port = up->cb.tcb->conn.local.port;
  1581.         up->namelen = SOCKSIZE;
  1582.  
  1583.         sp.p = up->peername;
  1584.         sp.in->sin_family = AF_INET;
  1585.         sp.in->sin_addr.s_addr = up->cb.tcb->conn.remote.address;
  1586.         sp.in->sin_port = up->cb.tcb->conn.remote.port;
  1587.         up->peernamelen = SOCKSIZE;
  1588.  
  1589.         /* Wake up the guy accepting it, and let him run */
  1590.         psignal(oup,1);
  1591.         pwait(NULL);
  1592.         break;
  1593.     default:    /* Ignore all other state transitions */
  1594.         break;
  1595.     }
  1596.     psignal(up,0);    /* In case anybody's waiting */
  1597. }
  1598. /* Discard data received on a TCP connection. Used after a receive shutdown or
  1599.  * close_s until the TCB disappears.
  1600.  */
  1601. static void
  1602. trdiscard(tcb,cnt)
  1603. struct tcb *tcb;
  1604. int cnt;
  1605. {
  1606.     struct mbuf *bp;
  1607.  
  1608.     recv_tcp(tcb,&bp,(int16)cnt);
  1609.     free_p(bp);
  1610. }
  1611. #ifdef    AX25
  1612. /* AX.25 receive upcall */
  1613. void
  1614. s_arcall(axp,cnt)
  1615. struct ax25_cb *axp;
  1616. int cnt;
  1617. {
  1618.     int ns;
  1619.     struct usock *up,*nup,*oup;
  1620.     union sp sp;
  1621.  
  1622.     up = itop(axp->user);
  1623.     /* When AX.25 data arrives for the first time the AX.25 listener
  1624.        is notified, if active. If the AX.25 listener is a server its
  1625.        socket is duplicated in the same manner as in s_tscall().
  1626.      */
  1627.     if (Axi_sock != -1 && axp->user == -1) {
  1628.         oup = up = itop(Axi_sock);
  1629.         /* From now on, use the same upcalls as the listener */
  1630.         axp->t_upcall = up->cb.ax25->t_upcall;
  1631.         axp->r_upcall = up->cb.ax25->r_upcall;
  1632.         axp->s_upcall = up->cb.ax25->s_upcall;
  1633.         if (up->cb.ax25->flags.clone) {
  1634.             /* Clone the socket */
  1635.             ns = socket(AF_AX25,SOCK_STREAM,0);
  1636.             nup = &Usock[ns];
  1637.             ASSIGN(*nup,*up);
  1638.             axp->user = ns;
  1639.             nup->cb.ax25 = axp;
  1640.             /* Allocate new memory for the name areas */
  1641.             nup->name = mallocw(sizeof(struct sockaddr_ax));
  1642.             nup->peername = mallocw(sizeof(struct sockaddr_ax));
  1643.             /* Store the new socket # in the old one */
  1644.             up->rdysock = ns;
  1645.             up = nup;
  1646.         } else {
  1647.             axp->user = Axi_sock;
  1648.             del_ax25(up->cb.ax25);
  1649.             up->cb.ax25 = axp;
  1650.             /* Allocate space for the peer's name */
  1651.             up->peername = mallocw(sizeof(struct sockaddr_ax));
  1652.             /* Store the old socket # in the old socket */
  1653.             up->rdysock = Axi_sock;
  1654.         }
  1655.         /* Load the addresses. Memory for the name has already
  1656.          * been allocated, either above or in the original bind.
  1657.          */
  1658.         sp.p = up->name;
  1659.         sp.ax->sax_family = AF_AX25;
  1660.         memcpy(sp.ax->ax25_addr,axp->local,AXALEN);
  1661.         memcpy(sp.ax->iface,axp->iface->name,ILEN);
  1662.         up->namelen = sizeof(struct sockaddr_ax);
  1663.  
  1664.         sp.p = up->peername;
  1665.         sp.ax->sax_family = AF_AX25;
  1666.         memcpy(sp.ax->ax25_addr,axp->remote,AXALEN);
  1667.         memcpy(sp.ax->iface,axp->iface->name,ILEN);
  1668.         up->peernamelen = sizeof(struct sockaddr_ax);
  1669.         /* Wake up the guy accepting it, and let him run */
  1670.         psignal(oup,1);
  1671.         pwait(NULL);
  1672.         return;
  1673.     }
  1674.     /* Wake up anyone waiting, and let them run */
  1675.     psignal(up,1);
  1676.     pwait(NULL);
  1677. }
  1678. /* AX.25 transmit upcall */
  1679. void
  1680. s_atcall(axp,cnt)
  1681. struct ax25_cb *axp;
  1682. int cnt;
  1683. {
  1684.     /* Wake up anyone waiting, and let them run */
  1685.     psignal(itop(axp->user),1);
  1686.     pwait(NULL);
  1687. }
  1688. /* AX25 state change upcall routine */
  1689. void
  1690. s_ascall(axp,old,new)
  1691. register struct ax25_cb *axp;
  1692. int old,new;
  1693. {
  1694.     int s;
  1695.     struct usock *up;
  1696.  
  1697.     s = axp->user;
  1698.     up = itop(s);
  1699.  
  1700.     switch(new){
  1701.     case LAPB_DISCONNECTED:
  1702.         /* Clean up. If the user has already closed the socket,
  1703.          * then up will be null (s was set to -1 by the close routine).
  1704.          * If not, then this is an abnormal close (e.g., a reset)
  1705.          * and clearing out the pointer in the socket structure will
  1706.          * prevent any further operations on what will be a freed
  1707.          * control block. Also wake up anybody waiting on events
  1708.          * related to this block so they will notice it disappearing.
  1709.          */
  1710.         if(up != NULLUSOCK){
  1711.             up->errcodes[0] = axp->reason;
  1712.             up->cb.ax25 = NULLAX25;
  1713.         }
  1714.         del_ax25(axp);
  1715.         break;
  1716.     default:    /* Other transitions are ignored */
  1717.         break;
  1718.     }
  1719.     psignal(up,0);    /* In case anybody's waiting */
  1720. }
  1721. #endif
  1722. #ifdef NETROM
  1723. /* NET/ROM receive upcall routine */
  1724. static void
  1725. s_nrcall(cb,cnt)
  1726. struct nr4cb *cb;
  1727. int cnt;
  1728. {
  1729.     /* Wake up anybody waiting for data, and let them run */
  1730.     psignal(itop(cb->user),1);
  1731.     pwait(NULL);
  1732. }
  1733. /* NET/ROM transmit upcall routine */
  1734. static void
  1735. s_ntcall(cb,cnt)
  1736. struct nr4cb *cb;
  1737. int cnt;
  1738. {
  1739.     /* Wake up anybody waiting to send data, and let them run */
  1740.     psignal(itop(cb->user),1);
  1741.     pwait(NULL);
  1742. }
  1743. /* NET/ROM state change upcall routine */
  1744. static void
  1745. s_nscall(cb,old,new)
  1746. struct nr4cb *cb;
  1747. int old,new;
  1748. {
  1749.     int s,ns;
  1750.     struct usock *up,*nup,*oup;
  1751.     union sp sp;
  1752.  
  1753.     s = cb->user;
  1754.     oup = up = itop(s);
  1755.  
  1756.      if(new == NR4STDISC && up != NULLUSOCK){
  1757.         /* Clean up. If the user has already closed the socket,
  1758.          * then up will be null (s was set to -1 by the close routine).
  1759.          * If not, then this is an abnormal close (e.g., a reset)
  1760.          * and clearing out the pointer in the socket structure will
  1761.          * prevent any further operations on what will be a freed
  1762.          * control block. Also wake up anybody waiting on events
  1763.          * related to this cb so they will notice it disappearing.
  1764.          */
  1765.          up->cb.nr4 = NULLNR4CB;
  1766.          up->errcodes[0] = cb->dreason;
  1767.      }
  1768.      if(new == NR4STCON && old == NR4STDISC){
  1769.         /* Handle an incoming connection. If this is a server cb,
  1770.          * then we're being handed a "clone" cb and we need to
  1771.          * create a new socket structure for it. In either case,
  1772.          * find out who we're talking to and wake up the guy waiting
  1773.          * for the connection.
  1774.          */
  1775.         if(cb->clone){
  1776.             /* Clone the socket */
  1777.             ns = socket(AF_NETROM,SOCK_SEQPACKET,0);
  1778.             nup = &Usock[ns];
  1779.             ASSIGN(*nup,*up);
  1780.             cb->user = ns;
  1781.             nup->cb.nr4 = cb;
  1782.             cb->clone = 0; /* to avoid getting here again */
  1783.             /* Allocate new memory for the name areas */
  1784.             nup->name = mallocw(sizeof(struct sockaddr_nr));
  1785.             nup->peername = mallocw(sizeof(struct sockaddr_nr));
  1786.             /* Store the new socket # in the old one */
  1787.             up->rdysock = ns;
  1788.             up = nup;
  1789.             s = ns;
  1790.         } else {
  1791.             /* Allocate space for the peer's name */
  1792.             up->peername = mallocw(sizeof(struct sockaddr_nr));
  1793.             /* Store the old socket # in the old socket */
  1794.             up->rdysock = s;
  1795.         }
  1796.         /* Load the addresses. Memory for the name has already
  1797.          * been allocated, either above or in the original bind.
  1798.          */
  1799.         sp.p = up->name;
  1800.         sp.nr->nr_family = AF_NETROM;
  1801.         ASSIGN(sp.nr->nr_addr,up->cb.nr4->local);
  1802.         up->namelen = sizeof(struct sockaddr_nr);
  1803.  
  1804.         sp.p = up->peername;
  1805.         sp.nr->nr_family = AF_NETROM;
  1806.         ASSIGN(sp.nr->nr_addr,up->cb.nr4->remote);
  1807.         up->peernamelen = sizeof(struct sockaddr_nr);
  1808.  
  1809.         /* Wake up the guy accepting it, and let him run */
  1810.         psignal(oup,1);
  1811.         pwait(NULL);
  1812.     }
  1813.      /* Ignore all other state transitions */    
  1814.     psignal(up,0);    /* In case anybody's waiting */
  1815. }
  1816. #endif
  1817.  
  1818. /* Verify address family and length according to the socket type */
  1819. static int
  1820. checkaddr(type,name,namelen)
  1821. int type;
  1822. char *name;
  1823. int namelen;
  1824. {
  1825.     register struct sockaddr *sp;
  1826.  
  1827.     sp = (struct sockaddr *)name;
  1828.     /* Verify length and address family according to protocol */
  1829.     switch(type){
  1830.     case TYPE_TCP:
  1831.     case TYPE_UDP:
  1832.         if(sp->sa_family != AF_INET
  1833.          || namelen != sizeof(struct sockaddr_in))
  1834.             return -1;
  1835.         break;
  1836. #ifdef    AX25
  1837.     case TYPE_AX25I:
  1838.     case TYPE_AX25UI:
  1839.         if(sp->sa_family != AF_AX25
  1840.          || namelen != sizeof(struct sockaddr_ax))
  1841.             return -1;
  1842.         break;
  1843. #endif
  1844. #ifdef    NETROM
  1845.     case TYPE_NETROML3:
  1846.     case TYPE_NETROML4:
  1847.         if(sp->sa_family != AF_NETROM
  1848.          || namelen != sizeof(struct sockaddr_nr))
  1849.             return -1;
  1850.         break;
  1851. #endif
  1852.     }
  1853.     return 0;
  1854. }
  1855. /* Issue an automatic bind of a local address */
  1856. static void
  1857. autobind(s,af)
  1858. int s,af;
  1859. {
  1860.     char buf[MAXSOCKSIZE];
  1861.     union sp sp;
  1862.  
  1863.     sp.p = buf;
  1864.     switch(af){
  1865.     case AF_INET:
  1866.         sp.in->sin_family = AF_INET;
  1867.         sp.in->sin_addr.s_addr = INADDR_ANY;
  1868.         sp.in->sin_port = Lport++;
  1869.         bind(s,sp.p,sizeof(struct sockaddr_in));
  1870.         break;
  1871. #ifdef    AX25
  1872.     case AF_AX25:
  1873.         sp.ax->sax_family = AF_AX25;
  1874.         sp.ax->ax25_addr[0] = '\0';    /* Unspecified */
  1875.         bind(s,sp.p,sizeof(struct sockaddr_ax));
  1876.         break;
  1877. #endif
  1878. #ifdef    NETROM
  1879.     case AF_NETROM:
  1880.         sp.nr->nr_family = AF_NETROM;
  1881.         memcpy(sp.nr->nr_addr.user,Mycall,AXALEN);
  1882.         memcpy(sp.nr->nr_addr.node,Mycall,AXALEN);
  1883.         bind(s,sp.p,sizeof(struct sockaddr_nr));
  1884.         break;
  1885. #endif
  1886.     }
  1887. }
  1888.  
  1889.